/**
 * 蓝牙数据源实现
 * 
 * 用途：实现DataSourceInterface接口，提供蓝牙设备数据采集功能
 * 方法：通过蓝牙连接真实的脑波设备，获取实时脑波数据
 * 原理：使用Android蓝牙API连接设备，解析蓝牙数据包并转换为标准数据格式
 */
package com.example.brain_wave.data

import com.example.brain_wave.ui.components.BrainWaveDataPoint
import com.example.brain_wave.ui.components.BrainWaveDataGenerator
import com.example.brain_wave.ui.components.NeuroSkyRawDataPoint
import com.example.brain_wave.bluetooth.parser.NeuroSkyDataParser
import com.example.brain_wave.bluetooth.model.NeuroSkyRawData
import android.content.Context
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothSocket
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.app.ActivityCompat
import kotlinx.coroutines.*
import java.io.IOException
import java.io.InputStream
import java.util.*

/**
 * 蓝牙数据源实现
 */
class BluetoothDataSource(private val context: Context) : DataSourceInterface {
    
    private var currentState = DataSourceState.IDLE
    private var dataCollectionJob: Job? = null
    
    // 蓝牙相关组件
    private var bluetoothAdapter: BluetoothAdapter? = null
    private var bluetoothSocket: BluetoothSocket? = null
    private var inputStream: InputStream? = null
    private var bluetoothDevice: BluetoothDevice? = null
    
    // NeuroSky SPP UUID
    private val SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
    
    // NeuroSky数据解析器
    private val neuroSkyParser = NeuroSkyDataParser()
    
    // 回调函数
    private var onStateChanged: ((DataSourceState) -> Unit)? = null
    private var onDataPointGenerated: ((BrainWaveDataPoint) -> Unit)? = null
    private var onRawDataGenerated: ((NeuroSkyRawDataPoint) -> Unit)? = null
    private var onError: ((String) -> Unit)? = null
    
    // 蓝牙配置参数
    private var deviceAddress: String? = null
    private var deviceName: String? = null
    
    // 512Hz数据收集相关
    private val rawValueBuffer = mutableListOf<Int>()
    private var lastSendTime = 0L
    private val sendIntervalMs = 1000L // 每秒发送一次
    private var latestNeuroSkyData: NeuroSkyRawData? = null

    override fun initialize(config: Map<String, Any>) {
        // 从配置中获取设备信息
        deviceAddress = config["deviceAddress"] as? String
        deviceName = config["deviceName"] as? String
        
        println("🔧 初始化蓝牙数据源")
        println("   - 设备名称: $deviceName")
        println("   - 设备地址: $deviceAddress")
        
        // 设置NeuroSky数据解析器的回调
        neuroSkyParser.setOnDataReceived { neuroSkyRawData ->
            // 保存最新的NeuroSky数据（除了rawValue）
            latestNeuroSkyData = neuroSkyRawData
            
            // 收集rawValue到缓冲区
            rawValueBuffer.add(neuroSkyRawData.rawValue)
            
            // 检查是否需要发送数据（每秒一次，且收集了足够的数据）
            val currentTime = System.currentTimeMillis()
            if (currentTime - lastSendTime >= sendIntervalMs && rawValueBuffer.size >= 512) {
                // 创建包含512Hz数据的NeuroSkyRawDataPoint
                val rawDataPoint = NeuroSkyRawDataPoint(
                    timestamp = neuroSkyRawData.timestamp,
                    rawValues = rawValueBuffer.take(512).toList(), // 取前512个值
                    delta = neuroSkyRawData.delta,
                    theta = neuroSkyRawData.theta,
                    lowAlpha = neuroSkyRawData.lowAlpha,
                    highAlpha = neuroSkyRawData.highAlpha,
                    lowBeta = neuroSkyRawData.lowBeta,
                    highBeta = neuroSkyRawData.highBeta,
                    lowGamma = neuroSkyRawData.lowGamma,
                    midGamma = neuroSkyRawData.midGamma,
                    attention = neuroSkyRawData.attention,
                    meditation = neuroSkyRawData.meditation,
                    poorSignal = neuroSkyRawData.poorSignal,
                    blinkStrength = neuroSkyRawData.blinkStrength
                )
                
                // 通知原始数据生成（用于发送到分析服务端）
                onRawDataGenerated?.invoke(rawDataPoint)
                
                // 清空缓冲区，保留多余的数据
                if (rawValueBuffer.size > 512) {
                    val remaining = rawValueBuffer.drop(512)
                    rawValueBuffer.clear()
                    rawValueBuffer.addAll(remaining)
                } else {
                    rawValueBuffer.clear()
                }
                
                lastSendTime = currentTime
            }
            
            // 生成BrainWaveDataPoint用于UI显示（保持原有逻辑）
            // 计算各频域的总功率
            val totalPower = (neuroSkyRawData.delta + neuroSkyRawData.theta + 
                            neuroSkyRawData.lowAlpha + neuroSkyRawData.highAlpha +
                            neuroSkyRawData.lowBeta + neuroSkyRawData.highBeta +
                            neuroSkyRawData.lowGamma + neuroSkyRawData.midGamma).toFloat()
            
            val dataPoint = BrainWaveDataPoint(
                timestamp = neuroSkyRawData.timestamp,
                deltaRatio = if (totalPower > 0) neuroSkyRawData.delta / totalPower else 0f,
                thetaRatio = if (totalPower > 0) neuroSkyRawData.theta / totalPower else 0f,
                alphaRatio = if (totalPower > 0) (neuroSkyRawData.lowAlpha + neuroSkyRawData.highAlpha) / totalPower else 0f,
                betaRatio = if (totalPower > 0) (neuroSkyRawData.lowBeta + neuroSkyRawData.highBeta) / totalPower else 0f,
                gammaRatio = if (totalPower > 0) (neuroSkyRawData.lowGamma + neuroSkyRawData.midGamma) / totalPower else 0f,
                signalQuality = if (neuroSkyRawData.poorSignal <= 200) (200 - neuroSkyRawData.poorSignal) / 200f else 0f
            )
            
            // 通知数据点生成（用于UI显示）
            onDataPointGenerated?.invoke(dataPoint)
        }
        
        updateState(DataSourceState.IDLE)
    }
    
    override suspend fun connect(): Boolean {
        if (currentState == DataSourceState.CONNECTED) {
            println("⚠️ 蓝牙设备已连接")
            return true
        }
        
        updateState(DataSourceState.CONNECTING)
        
        try {
            println("🔗 开始连接蓝牙设备: $deviceName ($deviceAddress)")
            
            // 初始化蓝牙适配器
            bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
            if (bluetoothAdapter == null) {
                throw Exception("设备不支持蓝牙")
            }
            
            if (!bluetoothAdapter!!.isEnabled) {
                throw Exception("蓝牙未开启")
            }
            
            // 检查蓝牙权限
            if (!hasBluetoothPermissions()) {
                throw Exception("缺少蓝牙权限")
            }
            
            // 获取蓝牙设备
            if (deviceAddress == null) {
                throw Exception("设备地址为空")
            }
            
            bluetoothDevice = bluetoothAdapter!!.getRemoteDevice(deviceAddress)
            if (bluetoothDevice == null) {
                throw Exception("无法获取蓝牙设备")
            }
            
            // 停止设备发现以提高连接性能
            bluetoothAdapter!!.cancelDiscovery()
            
            // 创建蓝牙Socket
            bluetoothSocket = bluetoothDevice!!.createRfcommSocketToServiceRecord(SPP_UUID)
            
            // 连接设备
            bluetoothSocket!!.connect()
            
            // 获取输入流
            inputStream = bluetoothSocket!!.inputStream
            
            updateState(DataSourceState.CONNECTED)
            println("✅ 蓝牙设备连接成功: $deviceName")
            return true
            
        } catch (e: IOException) {
            println("❌ 蓝牙连接失败 (IO异常): ${e.message}")
            updateState(DataSourceState.ERROR)
            onError?.invoke("蓝牙连接失败: ${e.message}")
            cleanupBluetoothResources()
            return false
        } catch (e: SecurityException) {
            println("❌ 蓝牙连接失败 (权限异常): ${e.message}")
            updateState(DataSourceState.ERROR)
            onError?.invoke("蓝牙权限错误: ${e.message}")
            cleanupBluetoothResources()
            return false
        } catch (e: Exception) {
            println("❌ 蓝牙连接失败: ${e.message}")
            updateState(DataSourceState.ERROR)
            onError?.invoke("蓝牙连接失败: ${e.message}")
            cleanupBluetoothResources()
            return false
        }
    }
    
    override suspend fun disconnect() {
        if (currentState == DataSourceState.IDLE || currentState == DataSourceState.DISCONNECTED) {
            return
        }
        
        // 停止数据采集
        stopDataCollection()
        
        // 清空数据缓冲区，确保不再发送数据
        rawValueBuffer.clear()
        lastSendTime = 0L
        latestNeuroSkyData = null
        
        // 清理蓝牙连接
        cleanupBluetoothResources()
        
        updateState(DataSourceState.DISCONNECTED)
        println("🔌 蓝牙设备已断开连接，数据发送已停止")
    }
    
    /**
     * 清理蓝牙连接资源
     */
    private fun cleanupBluetoothResources() {
        try {
            inputStream?.close()
        } catch (e: IOException) {
            // 忽略关闭异常
        }
        
        try {
            bluetoothSocket?.close()
        } catch (e: IOException) {
            // 忽略关闭异常
        }
        
        inputStream = null
        bluetoothSocket = null
        bluetoothDevice = null
    }
    
    /**
     * 检查蓝牙权限
     */
    private fun hasBluetoothPermissions(): Boolean {
        val requiredPermissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            listOf(
                android.Manifest.permission.BLUETOOTH_CONNECT,
                android.Manifest.permission.BLUETOOTH_SCAN
            )
        } else {
            listOf(
                android.Manifest.permission.BLUETOOTH,
                android.Manifest.permission.BLUETOOTH_ADMIN
            )
        }
        
        return requiredPermissions.all { permission ->
            ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
        }
    }
    
    override fun startDataCollection() {
        if (currentState != DataSourceState.CONNECTED) {
            onError?.invoke("蓝牙设备未连接，无法开始数据采集")
            return
        }
        
        if (dataCollectionJob?.isActive == true) {
            println("⚠️ 蓝牙数据采集已在进行中")
            return
        }
        
        updateState(DataSourceState.COLLECTING)
        
        dataCollectionJob = CoroutineScope(Dispatchers.IO).launch {
            println("🚀 开始蓝牙数据采集")
            
            val buffer = ByteArray(1024)
            
            while (isActive && currentState == DataSourceState.COLLECTING) {
                try {
                    // 从蓝牙设备读取数据
                    val bytesRead = inputStream?.read(buffer) ?: -1
                    
                    if (bytesRead == -1) {
                        // 连接已断开
                        throw IOException("蓝牙连接已断开")
                    }
                    
                    if (bytesRead > 0) {
                        val data = ByteArray(bytesRead)
                        System.arraycopy(buffer, 0, data, 0, bytesRead)
                        
                        // 使用NeuroSkyDataParser解析真实的蓝牙数据
                        neuroSkyParser.processData(data)
                        
                        println("📡 接收到蓝牙数据: ${bytesRead}字节")
                    }
                    
                    // 短暂延迟避免过度占用CPU
                    delay(10)
                    
                } catch (e: IOException) {
                    println("❌ 蓝牙数据读取失败: ${e.message}")
                    onError?.invoke("蓝牙数据读取失败: ${e.message}")
                    updateState(DataSourceState.ERROR)
                    break
                } catch (e: Exception) {
                    println("❌ 数据采集异常: ${e.message}")
                    onError?.invoke("数据采集异常: ${e.message}")
                    break
                }
            }
            
            println("📊 蓝牙数据采集已停止")
        }
    }
    
    override fun stopDataCollection() {
        if (dataCollectionJob?.isActive == true) {
            dataCollectionJob?.cancel()
            dataCollectionJob = null
        }
        
        if (currentState == DataSourceState.COLLECTING) {
            updateState(DataSourceState.CONNECTED)
        }
        
        println("⏹️ 停止蓝牙数据采集")
    }
    
    override fun getCurrentState(): DataSourceState = currentState
    
    override fun isConnected(): Boolean = 
        currentState == DataSourceState.CONNECTED || currentState == DataSourceState.COLLECTING
    
    override fun isCollecting(): Boolean = currentState == DataSourceState.COLLECTING
    
    override fun setOnStateChanged(callback: (DataSourceState) -> Unit) {
        onStateChanged = callback
    }
    
    override fun setOnDataPointGenerated(callback: (BrainWaveDataPoint) -> Unit) {
        onDataPointGenerated = callback
    }
    
    /**
     * 设置原始数据生成回调
     */
    fun setOnRawDataGenerated(callback: (NeuroSkyRawDataPoint) -> Unit) {
        onRawDataGenerated = callback
    }
    
    override fun setOnError(callback: (String) -> Unit) {
        onError = callback
    }
    
    override fun cleanup() {
        stopDataCollection()
        cleanupBluetoothResources()
        
        onStateChanged = null
        onDataPointGenerated = null
        onRawDataGenerated = null
        onError = null
        
        println("🧹 蓝牙数据源已清理")
    }
    
    /**
     * 更新状态并通知回调
     */
    private fun updateState(newState: DataSourceState) {
        val oldState = currentState
        currentState = newState
        
        if (oldState != newState) {
            println("📊 BluetoothDataSource状态变化: $oldState -> $newState")
            onStateChanged?.invoke(newState)
        }
    }
}